/**
 * Copyright (C) 2012-2013 jumei, Inc.
 * BeanCache.java
 * 2015年6月29日
 */
package org.goface.rpc.invoker;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

class BeanCache {
    protected Object beanInstance;
    protected Map<String, Method> methodCache = new ConcurrentHashMap<>(10);
    protected final static Map<String, Class<?>> wrapTypes = new HashMap<>();
    static {
        wrapTypes.put("int", Integer.class);
        wrapTypes.put("byte", Byte.class);
        wrapTypes.put("char", Character.class);
        wrapTypes.put("boolean", Boolean.class);
        wrapTypes.put("long", Long.class);
        wrapTypes.put("float", Float.class);
        wrapTypes.put("double", Double.class);
        wrapTypes.put("short", Short.class);
    }

    public BeanCache(Object instance) {
        beanInstance = instance;

    }

    protected Method getMethod(String name, Class<?>[] argsType) {
        StringBuilder signature = new StringBuilder();
        signature.append(name);
        for (Class<?> cl : argsType) {
            signature.append(cl.getCanonicalName());
        }
        Method method = methodCache.get(signature.toString());
        if (method == null) {
            // 反射 查找
            Method[] methods = beanInstance.getClass().getMethods();
            for (Method m : methods) {
                Class<?>[] parameterTypes = m.getParameterTypes();
                if (argsType.length != parameterTypes.length || !m.getName().equals(name)) {
                    continue;
                }
                boolean sameTypes = true;
                for (int i = 0; i < parameterTypes.length; ++i) {
                    if (parameterTypes[i].isPrimitive()) {
                        String clazzName = parameterTypes[i].getName();
                        parameterTypes[i] = wrapTypes.get(clazzName);
                    }

                    if (!parameterTypes[i].isAssignableFrom(argsType[i])) {
                        sameTypes = false;
                        break;
                    }

                }
                if (sameTypes) {
                    method = m;
                    methodCache.put(signature.toString(), method);
                    break;
                }
            }
        }
        return method;

    }
}